package wili.misc;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import wili.c.Ca;
import wili.c.File9a;
import wili.c.Misc9a;

/**
 *
 */
public class DemoList {
	static void underlying_collection() {
		ArrayList<String> lis1 = new ArrayList<>(Arrays.asList("aa", "bb", "cc", "xx", "yy"));
		int opt = 1;
		opt = 3;
		if (opt == 1) {
			List<String> lis2 = new ArrayList<>();
			lis2.addAll(lis1);
			lis1.remove("bb");
			Ca.log(1, "lis2=" + lis2);
		} else if (opt == 2) {
			Iterator<String> it = lis1.iterator();
			lis1.remove("bb");
			Ca.log(1, "lis2=" + Misc9a.listOfIterator(it));
			lis1.remove("cc");
			try {
				Ca.log(1, "lis2=" + Misc9a.listOfIterator(it));
			} catch (ConcurrentModificationException e) {
				Ca.log(1, e);
			}
		} else if (opt == 3) {
			//java有无依赖于大集的子集？大集增减元素后，子集同步增减。主要指List集合。
			//but sub list is readonly.
			List<String> lis2 = lis1.subList(0, 3);//子集只读
			lis1.add("ff");
			Ca.log("cc1:" + lis1);
			try {
				Ca.log("cc2:" + lis1);
				Ca.log("cc2:" + lis2);
			} catch (ConcurrentModificationException e) {
				e.printStackTrace();
			}
			List<String> lis3 = lis2.subList(1, 3);
			try {
				Ca.log("cc3:" + lis3);
			} catch (ConcurrentModificationException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		underlying_collection();
	}

	public static class ClassFileListener {
		public static void main(String[] args) {
			String[] path = { "C:\\Users\\C5348828\\AppData\\Roaming\\JetBrains",
					"C:\\Perforce\\b1a\\BUSMB_B1\\SBO\\dev\\Source\\WebClient" };
			new ClassFileListener().start(path, 30, 5);
		}

		public ClassFileListener() {
		}

		/**
		 *
		 * @param file
		 * @param clsRootName eg. target/classes
		 * @return
		 */
		public static File classFileOf(File file, String clsRootName) {
			File dad = file.getParentFile();
			File root = new File(dad, clsRootName);
			while (!root.exists()) {
				dad = dad.getParentFile();
				root = new File(dad, clsRootName);
			}
			String rela = File9a.relativePathOf(dad, file.getParentFile());
			File cdad = new File(root, rela);
			String fname = file.getName();
			if (file.getName().endsWith(".java")) {
				fname = fname.substring(0, fname.length() - 5) + ".class";
			}
			File ret = new File(cdad, fname);
			if (!ret.exists()) {
				new FileNotFoundException(ret.getAbsolutePath()).printStackTrace();
				return null;
			}
			return ret;
		}

		/**
		 * 在指定目录下查找指定秒数内被修改过的文件,最大查找深度<=maxDepth.
		 */
		public void start(String[] rootPaths, int inSeconds, int maxDepth) {
			Runnable run = new Runnable() {
				@Override
				public void run() {
					Map<File, long[]> toMap = new HashMap<>();
					int times = 0;
					while (true) {
						for (int i = 0; i < rootPaths.length; i++) {
							File rootDir = new File(rootPaths[i]);
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e) {
								throw new RuntimeException(e);
							}
							int[] fileNum = { 0 };
							List<File> toList = new ArrayList<>();
							final int inMillis = inSeconds * 1000;
							Predicate<File> cond = new Predicate<File>() {
								long time = System.currentTimeMillis();

								@Override
								public boolean test(File file) {
									++fileNum[0];
									File cfile = classFileOf(file, "target/classes");
									long nn = System.currentTimeMillis() - file.lastModified();
									//log(file.getName() + ", " + nn + "~" + inMillis);
									if (nn < inMillis) {
										return true;
									}
									return false;
								}
							};
							find_and_print_fileName(rootDir, 0, maxDepth, cond, toMap);
							++times;
							log("=====================" + times + " times, find in " + fileNum[0] + " files.");
						}
					}
				}
			};
			new Thread(run).start();
		}

		static void log(Object msg) {
			System.out.println(msg);
		}

		static void find_and_print_fileName(File from, int curDepth, int maxDepth, Predicate<File> cond,
				Map<File, long[]> toMap) {
			if (from.isFile()) {
				if (cond.test(from)) {
					long nowTime = System.currentTimeMillis();
					long[] tt = toMap.get(from);//[被修改的次数， 最近一次修改的时间]
					if (tt != null) {
						if (from.lastModified() == tt[1]) {
							return;
						}
						++tt[0];
						tt[1] = from.lastModified();
					} else {
						toMap.put(from, tt = new long[] { 1, from.lastModified() });
					}
					log(" " + toMap.size() + ", " + from.getName() + "\tin " + from.getParentFile().getAbsolutePath());
				}
			} else if (from.isDirectory()) {
				if (++curDepth > maxDepth)
					return;
				File[] ff = from.listFiles();
				for (File file : ff) {
					find_and_print_fileName(file, curDepth, maxDepth, cond, toMap);
				}
			}
		}
	}

	public static class DirListener {
		public static void main(String[] args) {
			String[] path = { "C:\\Users\\C5348828\\AppData\\Roaming\\JetBrains",
					"C:\\Perforce\\b1a\\BUSMB_B1\\SBO\\dev\\Source\\WebClient" };
			new DirListener().start(path, 30, 5);
		}

		public DirListener() {
		}

		/**
		 * 在指定目录下查找指定秒数内被修改过的文件,最大查找深度<=maxDepth.
		 */
		public void start(String[] rootPaths, int inSeconds, int maxDepth) {
			Runnable run = new Runnable() {
				@Override
				public void run() {
					Map<File, long[]> toMap = new HashMap<>();
					int times = 0;
					while (true) {
						for (int i = 0; i < rootPaths.length; i++) {
							File rootDir = new File(rootPaths[i]);
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e) {
								throw new RuntimeException(e);
							}
							int[] fileNum = { 0 };
							List<File> toList = new ArrayList<>();
							final int inMillis = inSeconds * 1000;
							Predicate<File> cond = new Predicate<File>() {
								long time = System.currentTimeMillis();

								@Override
								public boolean test(File file) {
									++fileNum[0];
									long nn = System.currentTimeMillis() - file.lastModified();
									//log(file.getName() + ", " + nn + "~" + inMillis);
									if (nn < inMillis) {
										return true;
									}
									return false;
								}
							};
							find_and_print_file00(rootDir, 0, maxDepth, cond, toMap);
							++times;
							log("=====================" + times + " times, find in " + fileNum[0] + " files.");
						}
					}
				}
			};
			new Thread(run).start();
		}

		static void log(Object msg) {
			System.out.println(msg);
		}

		static void find_and_print_file00(File from, int curDepth, int maxDepth, Predicate<File> cond,
				Map<File, long[]> toMap) {
			if (from.isFile()) {
				if (cond.test(from)) {
					long nowTime = System.currentTimeMillis();
					long[] tt = toMap.get(from);//[被修改的次数， 最近一次修改的时间]
					if (tt != null) {
						if (from.lastModified() == tt[1]) {
							return;
						}
						++tt[0];
						tt[1] = from.lastModified();
					} else {
						toMap.put(from, tt = new long[] { 1, from.lastModified() });
					}
					log(" " + toMap.size() + ", " + from.getName() + "\tin " + from.getParentFile().getAbsolutePath());
				}
			} else if (from.isDirectory()) {
				if (++curDepth > maxDepth)
					return;
				File[] ff = from.listFiles();
				for (File file : ff) {
					find_and_print_file00(file, curDepth, maxDepth, cond, toMap);
				}
			}
		}
	}
}
